package org.nnxy.foodboot.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.nnxy.foodboot.mapper.StatisticsMapper;

import org.nnxy.foodboot.service.StatisticsService;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据统计服务实现类
 * 提供食谱统计、用户交互统计、热门排行等数据查询功能
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class StatisticsServiceImpl implements StatisticsService {

    private final StatisticsMapper statisticsMapper;

    @Override
    public Map<String, Object> getRecipeStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 1. 获取食谱总数
            Long totalCount = statisticsMapper.countTotalRecipes();
            result.put("totalCount", totalCount != null ? totalCount : 0);
            
            // 2. 获取各分类统计
            Map<String, Long> flavorCount = countByFlavor();
            Map<String, Long> techniqueCount = countByTechnique();
            Map<String, Long> difficultyCount = countByDifficulty();
            Map<String, Long> categoryCount = countByCategory();
            
            // 3. 生成时间趋势数据 (最近7天)
            List<Map<String, Object>> trendData = new ArrayList<>();
            LocalDateTime now = LocalDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
            
            for (int i = 6; i >= 0; i--) {
                LocalDate date = now.minusDays(i).toLocalDate();
                LocalDateTime startOfDay = LocalDateTime.of(date, LocalTime.MIN);
                LocalDateTime endOfDay = LocalDateTime.of(date, LocalTime.MAX);
                
                long count = countRecipesByTimeRange(startOfDay, endOfDay);
                
                Map<String, Object> dayData = new HashMap<>();
                dayData.put("date", date.format(formatter));
                dayData.put("count", count);
                trendData.add(dayData);
            }
            
            // 4. 获取最近一年的月度统计
            List<Map<String, Object>> monthStats = getRecipeStatsByMonth(LocalDate.now().getYear());
            
            // 5. 组装结果数据
            result.put("flavorDistribution", flavorCount);
            result.put("techniqueDistribution", techniqueCount);
            result.put("difficultyDistribution", difficultyCount);
            result.put("categoryDistribution", categoryCount);
            result.put("trendData", trendData);
            result.put("monthlyStats", monthStats);
            
        } catch (Exception e) {
            log.error("获取食谱统计数据失败", e);
            result.put("error", "获取统计数据时发生错误");
        }
        
        return result;
    }

    @Override
    public Map<String, Object> getInteractionStatistics(Integer days) {
        // 默认统计最近30天
        int period = (days != null && days > 0) ? days : 30;
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 1. 获取总览数据
            Long browseCount = statisticsMapper.getTotalBrowseCount();
            browseCount = browseCount != null ? browseCount : 0L;
            
            // 计算收藏数量
            Long favoriteCount;
            try {
                favoriteCount = statisticsMapper.countFavoriteByTimeRange(
                        LocalDateTime.of(2000, 1, 1, 0, 0),
                        LocalDateTime.now());
                favoriteCount = favoriteCount != null ? favoriteCount : 0L;
            } catch (Exception e) {
                log.error("获取收藏统计失败", e);
                favoriteCount = 0L;
            }
            
            // 获取推荐点击量
            Long recommendClickCount;
            try {
                Map<String, Object> recommendStats = statisticsMapper.countRecommendationByTimeRange(
                        LocalDateTime.of(2000, 1, 1, 0, 0),
                        LocalDateTime.now());
                recommendClickCount = recommendStats != null ? 
                        ((Number) recommendStats.getOrDefault("clicked", 0)).longValue() : 0L;
            } catch (Exception e) {
                log.error("获取推荐点击统计失败", e);
                recommendClickCount = 0L;
            }
            
            Map<String, Object> overview = new HashMap<>();
            overview.put("browseCount", browseCount);
            overview.put("favoriteCount", favoriteCount);
            overview.put("recommendClickCount", recommendClickCount);
            
            // 计算点击转化率
            double clickRate = 0.0;
            try {
                Map<String, Object> recommendStats = statisticsMapper.countRecommendationByTimeRange(
                        LocalDateTime.of(2000, 1, 1, 0, 0),
                        LocalDateTime.now());
                long total = ((Number) recommendStats.getOrDefault("total", 0)).longValue();
                long clicked = ((Number) recommendStats.getOrDefault("clicked", 0)).longValue();
                clickRate = total > 0 ? (double) clicked / total : 0.0;
            } catch (Exception e) {
                log.error("计算点击转化率失败", e);
            }
            overview.put("recommendClickRate", String.format("%.2f", clickRate * 100) + "%");
            
            // 2. 获取用户浏览趋势
            List<Map<String, Object>> browseTrend = getBrowseTrend(period);
            
            // 3. 获取用户收藏趋势
            List<Map<String, Object>> favoriteTrend = getFavoriteTrend(period);
            
            // 4. 获取推荐点击率趋势
            List<Map<String, Object>> recommendationTrend = getRecommendationClickRateTrend(period);
            
            // 5. 组装结果数据
            result.put("overview", overview);
            result.put("browseTrend", browseTrend);
            result.put("favoriteTrend", favoriteTrend);
            result.put("recommendationTrend", recommendationTrend);
            
        } catch (Exception e) {
            log.error("获取用户交互统计数据失败", e);
            result.put("error", "获取统计数据时发生错误");
        }
        
        return result;
    }

    @Override
    public Map<String, Object> getPopularRecipes(Integer limit) {
        int limitCount = (limit != null && limit > 0) ? limit : 10;
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 1. 获取浏览量最高的食谱
            List<Map<String, Object>> mostViewed = getMostViewedRecipes(limitCount);
            
            // 2. 获取收藏最多的食谱
            List<Map<String, Object>> mostFavorited = getMostFavoritedRecipes(limitCount);
            
            // 3. 获取评分最高的食谱
            List<Map<String, Object>> highestRated = getHighestRatedRecipes(limitCount);
            
            // 4. 获取最近添加的食谱
            List<Map<String, Object>> recentAdded = getRecentAddedRecipes(limitCount);
            
            // 5. 组装结果数据
            result.put("mostViewed", mostViewed);
            result.put("mostFavorited", mostFavorited);
            result.put("highestRated", highestRated);
            result.put("recentAdded", recentAdded);
            
        } catch (Exception e) {
            log.error("获取热门食谱数据失败", e);
            result.put("error", "获取统计数据时发生错误");
        }
        
        return result;
    }
    
    @Override
    public List<Map<String, Object>> getRecentAddedRecipes(Integer limit) {
        int limitCount = (limit != null && limit > 0) ? limit : 10;
        try {
            return statisticsMapper.getRecentAddedRecipes(limitCount);
        } catch (Exception e) {
            log.error("获取最近添加食谱失败", e);
            return new ArrayList<>();
        }
    }
    
    @Override
    public Map<String, Object> getRecipeDetailWithStats(Long recipeId) {
        try {
            return statisticsMapper.getRecipeById(recipeId);
        } catch (Exception e) {
            log.error("获取食谱详情统计失败", e);
            return new HashMap<>();
        }
    }
    
    @Override
    public List<Map<String, Object>> getRecipeStatsByMonth(Integer year) {
        int targetYear = year != null ? year : LocalDate.now().getYear();
        try {
            return statisticsMapper.countRecipeByMonth(targetYear);
        } catch (Exception e) {
            log.error("获取食谱月度统计失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    public Map<String, Long> countByFlavor() {
        try {
            List<Map<String, Object>> flavorData = statisticsMapper.countRecipeByFlavor();
            return flavorData.stream()
                    .collect(Collectors.toMap(
                            map -> (String) map.get("name"),
                            map -> ((Number) map.get("value")).longValue()
                    ));
        } catch (Exception e) {
            log.error("统计口味分布失败", e);
            return new HashMap<>();
        }
    }

    @Override
    public Map<String, Long> countByTechnique() {
        try {
            List<Map<String, Object>> techniqueData = statisticsMapper.countRecipeByTechnique();
            return techniqueData.stream()
                    .collect(Collectors.toMap(
                            map -> (String) map.get("name"),
                            map -> ((Number) map.get("value")).longValue()
                    ));
        } catch (Exception e) {
            log.error("统计技巧分布失败", e);
            return new HashMap<>();
        }
    }

    @Override
    public Map<String, Long> countByDifficulty() {
        try {
            List<Map<String, Object>> difficultyData = statisticsMapper.countRecipeByDifficulty();
            return difficultyData.stream()
                    .collect(Collectors.toMap(
                            map -> (String) map.get("name"),
                            map -> ((Number) map.get("value")).longValue()
                    ));
        } catch (Exception e) {
            log.error("统计难度分布失败", e);
            return new HashMap<>();
        }
    }
    
    @Override
    public Map<String, Long> countByCategory() {
        try {
            List<Map<String, Object>> categoryData = statisticsMapper.countRecipeByCategory();
            return categoryData.stream()
                    .collect(Collectors.toMap(
                            map -> (String) map.get("name"),
                            map -> ((Number) map.get("value")).longValue()
                    ));
        } catch (Exception e) {
            log.error("统计分类分布失败", e);
            return new HashMap<>();
        }
    }

    @Override
    public long countRecipesByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            Long count = statisticsMapper.countRecipeByTimeRange(startTime, endTime);
            return count != null ? count : 0;
        } catch (Exception e) {
            log.error("统计时间范围内食谱数量失败", e);
            return 0;
        }
    }

    @Override
    public long countBrowseByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            Long count = statisticsMapper.countBrowseByTimeRange(startTime, endTime);
            return count != null ? count : 0;
        } catch (Exception e) {
            log.error("统计时间范围内浏览数量失败", e);
            return 0;
        }
    }

    @Override
    public long countFavoriteByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            Long count = statisticsMapper.countFavoriteByTimeRange(startTime, endTime);
            return count != null ? count : 0;
        } catch (Exception e) {
            log.error("统计时间范围内收藏数量失败", e);
            return 0;
        }
    }

    @Override
    public long countRecommendationByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            Map<String, Object> stats = statisticsMapper.countRecommendationByTimeRange(startTime, endTime);
            return stats != null ? ((Number) stats.getOrDefault("total", 0)).longValue() : 0;
        } catch (Exception e) {
            log.error("统计时间范围内推荐记录数量失败", e);
            return 0;
        }
    }

    @Override
    public long countRecommendationClicksByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
        try {
            Map<String, Object> stats = statisticsMapper.countRecommendationByTimeRange(startTime, endTime);
            return stats != null ? ((Number) stats.getOrDefault("clicked", 0)).longValue() : 0;
        } catch (Exception e) {
            log.error("统计时间范围内推荐点击数量失败", e);
            return 0;
        }
    }

    @Override
    public List<Map<String, Object>> getMostViewedRecipes(Integer limit) {
        int limitCount = (limit != null && limit > 0) ? limit : 10;
        try {
            return statisticsMapper.getMostViewedRecipes(limitCount);
        } catch (Exception e) {
            log.error("获取浏览量最高的食谱失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getMostFavoritedRecipes(Integer limit) {
        int limitCount = (limit != null && limit > 0) ? limit : 10;
        try {
            return statisticsMapper.getMostFavoritedRecipes(limitCount);
        } catch (Exception e) {
            log.error("获取收藏最多的食谱失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getHighestRatedRecipes(Integer limit) {
        int limitCount = (limit != null && limit > 0) ? limit : 10;
        try {
            return statisticsMapper.getHighestRatedRecipes(limitCount);
        } catch (Exception e) {
            log.error("获取评分最高的食谱失败", e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<Map<String, Object>> getBrowseTrend(int days) {
        List<Map<String, Object>> trend = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        
        try {
            // 生成每天的浏览数据
            for (int i = days - 1; i >= 0; i--) {
                LocalDate date = now.minusDays(i).toLocalDate();
                LocalDateTime startOfDay = LocalDateTime.of(date, LocalTime.MIN);
                LocalDateTime endOfDay = LocalDateTime.of(date, LocalTime.MAX);
                
                Long count = statisticsMapper.countBrowseByTimeRange(startOfDay, endOfDay);
                
                Map<String, Object> dayData = new HashMap<>();
                dayData.put("date", date.format(formatter));
                dayData.put("count", count != null ? count : 0);
                trend.add(dayData);
            }
        } catch (Exception e) {
            log.error("获取浏览趋势数据失败", e);
        }
        
        return trend;
    }

    @Override
    public List<Map<String, Object>> getFavoriteTrend(int days) {
        List<Map<String, Object>> trend = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        
        try {
            // 生成每天的收藏数据
            for (int i = days - 1; i >= 0; i--) {
                LocalDate date = now.minusDays(i).toLocalDate();
                LocalDateTime startOfDay = LocalDateTime.of(date, LocalTime.MIN);
                LocalDateTime endOfDay = LocalDateTime.of(date, LocalTime.MAX);
                
                Long count = statisticsMapper.countFavoriteByTimeRange(startOfDay, endOfDay);
                
                Map<String, Object> dayData = new HashMap<>();
                dayData.put("date", date.format(formatter));
                dayData.put("count", count != null ? count : 0);
                trend.add(dayData);
            }
        } catch (Exception e) {
            log.error("获取收藏趋势数据失败", e);
        }
        
        return trend;
    }

    @Override
    public List<Map<String, Object>> getRecommendationClickRateTrend(int days) {
        List<Map<String, Object>> trend = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        
        try {
            // 生成每天的推荐点击率数据
            for (int i = days - 1; i >= 0; i--) {
                LocalDate date = now.minusDays(i).toLocalDate();
                LocalDateTime startOfDay = LocalDateTime.of(date, LocalTime.MIN);
                LocalDateTime endOfDay = LocalDateTime.of(date, LocalTime.MAX);
                
                Map<String, Object> stats = statisticsMapper.countRecommendationByTimeRange(startOfDay, endOfDay);
                
                long total = stats != null ? ((Number) stats.getOrDefault("total", 0)).longValue() : 0;
                long clicked = stats != null ? ((Number) stats.getOrDefault("clicked", 0)).longValue() : 0;
                
                // 计算点击率
                double rate = total > 0 ? (double) clicked / total : 0;
                
                Map<String, Object> dayData = new HashMap<>();
                dayData.put("date", date.format(formatter));
                dayData.put("rate", rate);
                dayData.put("total", total);
                dayData.put("clicked", clicked);
                trend.add(dayData);
            }
        } catch (Exception e) {
            log.error("获取推荐点击率趋势数据失败", e);
        }
        
        return trend;
    }

    @Override
    public Map<String, Object> getCustomRangeStats(LocalDate startDate, LocalDate endDate, String type) {
        if (startDate == null) {
            throw new IllegalArgumentException("开始日期不能为空");
        }
        
        // 如果结束日期为空，使用当前日期
        LocalDate end = endDate != null ? endDate : LocalDate.now();
        
        // 验证日期范围
        if (startDate.isAfter(end)) {
            throw new IllegalArgumentException("开始日期不能晚于结束日期");
        }
        
        // 转换为LocalDateTime
        LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
        LocalDateTime endDateTime = LocalDateTime.of(end, LocalTime.MAX);
        
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 根据统计类型获取不同的数据
            if ("all".equalsIgnoreCase(type) || "browse".equalsIgnoreCase(type)) {
                // 获取浏览量数据
                long browseCount = countBrowseByTimeRange(startDateTime, endDateTime);
                result.put("browseCount", browseCount);
                
                // 获取每日浏览趋势
                List<Map<String, Object>> browseTrend = new ArrayList<>();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                
                // 遍历每一天
                LocalDate current = startDate;
                while (!current.isAfter(end)) {
                    LocalDateTime dayStart = LocalDateTime.of(current, LocalTime.MIN);
                    LocalDateTime dayEnd = LocalDateTime.of(current, LocalTime.MAX);
                    
                    long dayCount = countBrowseByTimeRange(dayStart, dayEnd);
                    
                    Map<String, Object> dayData = new HashMap<>();
                    dayData.put("date", current.format(formatter));
                    dayData.put("count", dayCount);
                    browseTrend.add(dayData);
                    
                    current = current.plusDays(1);
                }
                
                result.put("browseTrend", browseTrend);
            }
            
            if ("all".equalsIgnoreCase(type) || "favorite".equalsIgnoreCase(type)) {
                // 获取收藏量数据
                long favoriteCount = countFavoriteByTimeRange(startDateTime, endDateTime);
                result.put("favoriteCount", favoriteCount);
                
                // 获取每日收藏趋势
                List<Map<String, Object>> favoriteTrend = new ArrayList<>();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                
                // 遍历每一天
                LocalDate current = startDate;
                while (!current.isAfter(end)) {
                    LocalDateTime dayStart = LocalDateTime.of(current, LocalTime.MIN);
                    LocalDateTime dayEnd = LocalDateTime.of(current, LocalTime.MAX);
                    
                    long dayCount = countFavoriteByTimeRange(dayStart, dayEnd);
                    
                    Map<String, Object> dayData = new HashMap<>();
                    dayData.put("date", current.format(formatter));
                    dayData.put("count", dayCount);
                    favoriteTrend.add(dayData);
                    
                    current = current.plusDays(1);
                }
                
                result.put("favoriteTrend", favoriteTrend);
            }
            
            if ("all".equalsIgnoreCase(type) || "recommendation".equalsIgnoreCase(type)) {
                // 获取推荐数据
                long recommendCount = countRecommendationByTimeRange(startDateTime, endDateTime);
                long clickCount = countRecommendationClicksByTimeRange(startDateTime, endDateTime);
                double clickRate = recommendCount > 0 ? (double) clickCount / recommendCount : 0.0;
                
                result.put("recommendCount", recommendCount);
                result.put("clickCount", clickCount);
                result.put("clickRate", String.format("%.2f", clickRate * 100) + "%");
                
                // 获取每日推荐点击率趋势
                List<Map<String, Object>> recommendTrend = new ArrayList<>();
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                
                // 遍历每一天
                LocalDate current = startDate;
                while (!current.isAfter(end)) {
                    LocalDateTime dayStart = LocalDateTime.of(current, LocalTime.MIN);
                    LocalDateTime dayEnd = LocalDateTime.of(current, LocalTime.MAX);
                    
                    long dayRecommendCount = countRecommendationByTimeRange(dayStart, dayEnd);
                    long dayClickCount = countRecommendationClicksByTimeRange(dayStart, dayEnd);
                    double dayRate = dayRecommendCount > 0 ? (double) dayClickCount / dayRecommendCount : 0.0;
                    
                    Map<String, Object> dayData = new HashMap<>();
                    dayData.put("date", current.format(formatter));
                    dayData.put("total", dayRecommendCount);
                    dayData.put("clicked", dayClickCount);
                    dayData.put("rate", dayRate);
                    recommendTrend.add(dayData);
                    
                    current = current.plusDays(1);
                }
                
                result.put("recommendTrend", recommendTrend);
            }
            
            // 添加时间范围信息
            result.put("startDate", startDate.toString());
            result.put("endDate", end.toString());
            result.put("type", type);
            
        } catch (Exception e) {
            log.error("获取自定义时间范围统计数据失败", e);
            result.put("error", "获取统计数据时发生错误：" + e.getMessage());
        }
        
        return result;
    }
} 